/**
  ******************************************************************************
  * @file 	
  * @brief  
  ******************************************************************************
  */
  
#include "zbADC.h"

uint16_t Samples[3];

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

//DMA_InitTypeDef DMA_InitStructure;
//__IO uint16_t ADCConvertedValue;

/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void GPIO_Configuration(void);
void disableADC(void);

void initADC()
{
	ADC_InitTypeDef       ADC_InitStructure;
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
  DMA_InitTypeDef       DMA_InitStructure;
  GPIO_InitTypeDef      GPIO_InitStructure;

  /* Enable ADC3, DMA2 and GPIO clocks ****************************************/
  RCC_AHB1PeriphClockCmd(ZANAL_DMA_CLK | ZANAL_GPIO1CLK, ENABLE);
  RCC_APB2PeriphClockCmd(ZANAL_ADCCLK, ENABLE);

  /* DMA2 Stream0 channel0 configuration **************************************/
  DMA_InitStructure.DMA_Channel = ZANAL_DMA_CHAN;  
  DMA_InitStructure.DMA_PeripheralBaseAddr = ZANAL_DR;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&Samples[0];
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_BufferSize = 3;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  //DMA_Init(ZANAL_DMA_STREAM, &DMA_InitStructure);
  //DMA_Cmd(ZANAL_DMA_STREAM, ENABLE);

  /* Configure ADC3 Channel12 pin as analog input ******************************/
  GPIO_InitStructure.GPIO_Pin = ZANAL_PIN1 | ZANAL_PIN2 | ZANAL_PIN3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(ZANAL_PIN1_PORT, &GPIO_InitStructure);

  /* ADC Common Init **********************************************************/
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent ;
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
  ADC_CommonInit(&ADC_CommonInitStructure);

  /* ADC3 Init ****************************************************************/
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  ADC_InitStructure.ADC_ExternalTrigConv = 0;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfConversion = 3;
  ADC_Init(ZANAL_ADC, &ADC_InitStructure);

  /* ADC3 regular channel12 configuration *************************************/
  ADC_RegularChannelConfig(ZANAL_ADC, ZANAL_ADCCHAN1, 1, ADC_SampleTime_15Cycles  );
  //ADC_RegularChannelConfig(ZANAL_ADC, ZANAL_ADCCHAN2, 2, ADC_SampleTime_15Cycles  );
  //ADC_RegularChannelConfig(ZANAL_ADC, ZANAL_ADCCHAN3, 3, ADC_SampleTime_15Cycles  );

  //ADC_DMARequestAfterLastTransferCmd(ZANAL_ADC, ENABLE);

  /* Enable ADC3 DMA */
  //ADC_DMACmd(ZANAL_ADC, ENABLE);

  /* Enable ADC3 */
  ADC_Cmd(ZANAL_ADC, ENABLE);

  ADC_SoftwareStartConv(ZANAL_ADC);
}


void updateADC()
{
//	u8 channelsChanged = 0;
	u8 cont = false;
	
	// if there has been a change in the enabled state
	// of at least some perph
	if(mygVars->enabled != newgVars->enabled)
	{
		// if we were off 
		if(!(mygVars->enabled & enADC))
		{
			// and now we are on
			if(newgVars->enabled & enADC)
			{
				initADC();
				// update to know that we are on now
				mygVars->enabled = (mygVars->enabled | enADC);	
				cont = true;
			}
		}
		// if we were on
		if(mygVars->enabled & enADC)
		{
			// and now we are off
			if(!(newgVars->enabled & enADC))
			{
				disableADC();
				// clear bit so we are off next time
				mygVars->enabled = (mygVars->enabled & !enADC);
			}
		}
	}
	
	// if we get to this point and we are disabled just ret
	if(!(mygVars->enabled & enADC) && (cont == false))
	{
		return;
	}

	if(ADC_GetFlagStatus(ZANAL_ADC, ADC_FLAG_EOC) == SET)
	{
		mygVars->ADCIN1 = ZANAL_VALUE;
	}
}

void disableADC()
{

  // disable adc clocks
  RCC_APB2PeriphClockCmd(ZANAL_ADCCLK, DISABLE);
}


/**
  * @brief  Configures the different system clocks.
  * @param  None
  * @retval None
  */
void RCC_Configuration(void)
{
  /* Enable peripheral clocks ------------------------------------------------*/
  // enable the adc clock
  RCC_APB1PeriphClockCmd( ZANAL_GPIO1CLK, ENABLE);
  RCC_APB1PeriphClockCmd( ZANAL_DMA_CLK, ENABLE);
  /* Enable ADC1 and GPIOC clock */
  RCC_APB2PeriphClockCmd( ZANAL_ADCCLK, ENABLE );
}

/**
  * @brief  Configures the different GPIO ports.
  * @param  None
  * @retval None
  */
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* Configure PC.04 (ADC Channel14) as analog input -------------------------*/
  GPIO_InitStructure.GPIO_Pin = ZANAL_PIN1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(ZANAL_PIN1_PORT, &GPIO_InitStructure);
}

void testADC(void)
{
	u8 i = 0;											
	newgVars->enabled = newgVars->enabled | enADC;
	printf("ADC Test\r\n");
	updateADC();
	debugChar = 'a';
	while(debugChar == 'a')
	{
		updateADC();
		printf("%d ADC1:0x%x ADC2:0x%x FQ:0x%x",i, Samples[0], Samples[1], Samples[2]  );
		printf(" || ADC->SR:0x%x ADC->DR:0x%x ADC->CR1:0x%x ", ADC3->SR, ADC3->DR, ADC3->CR1  );
		printf(" || DMA2->LISR:0x%x DMA2->HISR:0x%x", DMA2->LISR, DMA2->HISR );
		if(ADC_GetFlagStatus(ZANAL_ADC, ADC_FLAG_OVR) == SET)
		{
		  printf(" || ORE!");
		  ADC_ClearFlag(ZANAL_ADC, ADC_FLAG_OVR);
		  initADC();
		}
		printf("\r\n"); 
		Delay(1000);

		i++;
	}
//	initADC();
//	while(1)
//	{
//  		/* convert the ADC value (from 0 to 0xFFF) to a voltage value (from 0V to 3.3V)*/
//    	ADC3ConvertedVoltage = ADC3ConvertedValue *3300/0xFFF;
//		//Delay(1000);
//	}
}
